package project

import (
	"context"
	"fmt"
	"os"
	"os/exec"
	"path"
	"runtime"
	"strings"

	"gitee.com/zzl/pag/internal/base"
	"github.com/AlecAivazis/survey/v2"
	"github.com/fatih/color"
)

// Project is a project template.
type Project struct {
	Name    string
	Path    string
	ModPath string
}

// New new a project from remote repo.
func (p *Project) New(ctx context.Context, dir string, layout string, branch string) error {
	to := path.Join(dir, p.Name)
	if _, err := os.Stat(to); !os.IsNotExist(err) {
		fmt.Printf("%s already exists\n", p.Name)
		override := false
		prompt := &survey.Confirm{
			Message: "Do you want to override the folder ?",
			Help:    "Delete the existing folder and create the project.",
		}
		e := survey.AskOne(prompt, &override)
		if e != nil {
			return e
		}
		if !override {
			return err
		}
		_ = os.RemoveAll(to)
	}
	fmt.Printf("🚀 Creating service %s, layout repo is %s, please wait a moment.\n\n", p.Name, layout)
	repo := base.NewRepo(layout, branch)

	projectDir := p.Path

	if p.ModPath != "" {
		p.Path = p.ModPath
	}

	if err := repo.CopyTo(ctx, to, p.Path, []string{".git", ".github"}); err != nil {
		return err
	}

	e := os.Rename(
		path.Join(to, "cmd", "server"),
		path.Join(to, "cmd", p.Name),
	)
	if e != nil {
		return e
	}

	err := p.formatCode(to)
	if err != nil {
		return err
	}

	// base.Tree(to, dir)

	fmt.Printf("\n🍺 Project creation succeeded %s\n", color.GreenString(p.Name))
	fmt.Print("💻 Use the following command to start the project 👇:\n\n")
	fmt.Println(color.WhiteString("$ cd %s", projectDir))
	fmt.Println(color.WhiteString("$ go mod tidy -v"))
	fmt.Printf("\n🎉 Enjoy Your Code\n\n")
	return nil
}

func (p *Project) formatCode(path string) error {
	format := []string{"get", "golang.org/x/tools/cmd/goimports@latest"}
	if strings.Compare(runtime.Version(), "go.15") == 1 {
		format[0] = "install"
	}
	cmd := exec.Command("go", format...)
	cmd.Stderr = os.Stderr
	cmd.Stdout = os.Stdout
	err := cmd.Run()
	if err != nil {
		return err
	}

	w := exec.Command("goimports", "-w", path)
	w.Stderr = os.Stderr
	w.Stdout = os.Stdout
	err = w.Run()
	if err != nil {
		return err
	}
	return nil
}
